package com.ylr.blog.framework.service.impl;

import com.ylr.base.common.dto.NameValue;
import com.ylr.base.common.enums.CommonEnum;
import com.ylr.base.common.enums.ResultEnum;
import com.ylr.base.common.exception.YlrException;
import com.ylr.blog.framework.service.BlogTagRelationService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ylr.blog.framework.entity.BlogTagEntity;
import com.ylr.blog.framework.entity.BlogTagRelationEntity;
import com.ylr.blog.framework.mapper.BlogTagRelationMapper;
import com.ylr.base.framework.service.SnowflakeService;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-05-23 11:38:53
 * className: BlogTagRelationServiceImpl
 * version: 1.0
 * description:
 */
@Service("blogTabRelationService")
@AllArgsConstructor
public class BlogTagRelationServiceImpl extends ServiceImpl<BlogTagRelationMapper, BlogTagRelationEntity> implements BlogTagRelationService {

    private final static Logger log = LoggerFactory.getLogger(BlogTagRelationServiceImpl.class);

    private final SnowflakeService snowflakeService;

    @Transactional
    @Override
    public void saveBlogTagRelation(Long blogId, List<Long> tagIdList) {

        Date date = new Date();
        int sort = 1;

        if (Objects.isNull(tagIdList)) {
            tagIdList = Collections.emptyList();
        }
        if (tagIdList.size() > 10) {
            log.info("博客标签不能大于十个。size={} tagIdList={}", tagIdList.size(), tagIdList);
            throw new YlrException(ResultEnum.REQUEST_FAIL.getCode(), "博客标签不能大于十个");
        }

        // 查询博客已关联的博客标签列表
        LambdaQueryWrapper<BlogTagRelationEntity> blogTagRelationLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询字段
        blogTagRelationLambdaQueryWrapper.select(BlogTagRelationEntity::getId, BlogTagRelationEntity::getTagId);
        // 匹配条件
        blogTagRelationLambdaQueryWrapper.eq(BlogTagRelationEntity::getBlogId, blogId)
                .eq(BlogTagRelationEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 查询数据
        List<BlogTagRelationEntity> blogTagRelationList = baseMapper.selectList(blogTagRelationLambdaQueryWrapper);

        // 数据映射
        Map<Long, BlogTagRelationEntity> longBlogTagRelationMap = blogTagRelationList.stream().collect(Collectors.toMap(BlogTagRelationEntity::getTagId, Function.identity()));

        List<BlogTagRelationEntity> saveBlogTagRelationList = new ArrayList<>();
        List<BlogTagRelationEntity> updateblogTagRelationList = new ArrayList<>();
        List<Long> removeTagIdList = new ArrayList<>();

        // 1、数据处理
        if (tagIdList.isEmpty()) {
            // 博客关联博客标签主键列表为空
            removeTagIdList = new ArrayList<>(longBlogTagRelationMap.keySet());
        } else if (blogTagRelationList.isEmpty()) {
            // 博客原来没有关联的博客标签
            for (Long tagId : tagIdList) {
                BlogTagRelationEntity blogTagRelation = this.getBlogTagRelation(blogId, tagId, sort++, date);
                // 记录数据
                saveBlogTagRelationList.add(blogTagRelation);
            }
        } else {
            // 博客新关联博客标签主键列表 和 博客已关联的博客标签集合 进行处理操作
            for (Long tagId : tagIdList) {
                /*
                    从菜单主键集合中删除菜单主键
                    1、删除成功，角色已关联该菜单，跟新数据
                    2、删除失败，角色未关联该菜单，需要进行关联
                 */
                BlogTagRelationEntity blogTagRelation = longBlogTagRelationMap.remove(tagId);
                if (Objects.isNull(blogTagRelation)) {
                    blogTagRelation = this.getBlogTagRelation(blogId, tagId, sort++, date);
                    // 记录数据
                    saveBlogTagRelationList.add(blogTagRelation);
                } else {
                    blogTagRelation.setSort(sort++);
                    // 记录数据
                    updateblogTagRelationList.add(blogTagRelation);
                }
            }
        }
        // 2、剩余数据处理
        if (!longBlogTagRelationMap.isEmpty()) {
            // 角色已关联菜单主键集合不为空，则说明集合剩余的元素，角色已经取消关联，需要删除
            removeTagIdList = new ArrayList<>(longBlogTagRelationMap.keySet());
        }
        // 3、处理结果入库
        if (!saveBlogTagRelationList.isEmpty()) {
            // 需要新关联的博客标签不为空
            log.info("博客关联博客标签");
            this.saveBatch(saveBlogTagRelationList);
        }
        if (!updateblogTagRelationList.isEmpty()) {
            log.info("修改博客关联博客标签");
            this.updateBatchById(updateblogTagRelationList);
        }
        if (!removeTagIdList.isEmpty()) {
            log.info("删除博客关联博客标签");
            this.deleteBlogTagRelation(Collections.singletonList(blogId), removeTagIdList);
        }
        log.info("博客关联博客标签完成");
    }

    @Transactional
    @Override
    public void copyBlogTagRelation(Long fromBlogId, Long targetBlogId) {
        // 查询数据
        List<Long> tagIdList = baseMapper.selectTagIdList(fromBlogId, CommonEnum.DELETE_NO.getValue());
        if (tagIdList.isEmpty()) {
            log.info("来源博客关联的博客标签为空。fromBlogId={}", fromBlogId);
            return;
        }
        // 复制数据
        List<BlogTagRelationEntity> saveBlogTagRelationList = new ArrayList<>();
        Date date = new Date();
        int sort = 1;
        for (Long tagId : tagIdList) {
            BlogTagRelationEntity blogTagRelation = this.getBlogTagRelation(targetBlogId, tagId, sort++, date);
            // 记录数据
            saveBlogTagRelationList.add(blogTagRelation);
        }
        boolean bool = this.saveBatch(saveBlogTagRelationList);
        log.info("复制博客关联博客标签完成。bool={}", bool);
    }

    @Override
    public List<Long> getTagIdList(Long blogId) {
        return baseMapper.selectTagIdList(blogId, CommonEnum.DELETE_NO.getValue());
    }

    @Override
    public List<NameValue<String>> getBlogTagList(Long blogId) {
        List<BlogTagEntity> blogTagList = baseMapper.getBlogTagList(blogId, CommonEnum.DELETE_NO.getValue());
        return blogTagList.stream()
                .map(blogTag -> new NameValue<>(blogTag.getName(), blogTag.getId().toString()))
                .collect(Collectors.toList());
    }

    @Override
    public void deleteBlogTagRelation(Long blogId) {
        LambdaUpdateWrapper<BlogTagRelationEntity> blogTagRelationLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        blogTagRelationLambdaUpdateWrapper.set(BlogTagRelationEntity::getDeleteStatus, CommonEnum.DELETE_YES.getValue())
                .set(BlogTagRelationEntity::getDeleteTime, new Date());
        // 匹配条件
        blogTagRelationLambdaUpdateWrapper.eq(BlogTagRelationEntity::getBlogId, blogId)
                .eq(BlogTagRelationEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 更新数据
        int count = baseMapper.update(null, blogTagRelationLambdaUpdateWrapper);
        log.info("博客关联博客标签删除完成。blogId={} count={}", blogId, count);
    }

    @Override
    public void removeBlogTagRelation(List<Long> blogIdList) {
        this.deleteBlogTagRelation(blogIdList, null);
    }

    /**
     * 删除博客关联博客标签
     * @param blogIdList 博客主键列表
     * @param tagIdList  博客标签主键列表
     */
    private void deleteBlogTagRelation(List<Long> blogIdList, List<Long> tagIdList) {
        LambdaUpdateWrapper<BlogTagRelationEntity> blogTagRelationLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        blogTagRelationLambdaUpdateWrapper.set(BlogTagRelationEntity::getDeleteStatus, CommonEnum.DELETE_YES.getValue())
                .set(BlogTagRelationEntity::getDeleteTime, new Date());
        // 匹配条件
        blogTagRelationLambdaUpdateWrapper.in(!CollectionUtils.isEmpty(blogIdList), BlogTagRelationEntity::getBlogId, blogIdList)
                .in(!CollectionUtils.isEmpty(tagIdList), BlogTagRelationEntity::getTagId, tagIdList)
                .eq(BlogTagRelationEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 更新数据
        int count = baseMapper.update(null, blogTagRelationLambdaUpdateWrapper);
        log.info("博客关联博客标签删除完成。count={}", count);
    }

    /**
     * 生成博客关联博客标签实体类对象
     * @param blogId 博客主键
     * @param tagId  博客标签主键
     * @param sort   排序等级
     * @param date   操作日期
     * @return 博客关联博客标签对象
     */
    private BlogTagRelationEntity getBlogTagRelation(Long blogId, Long tagId, Integer sort, Date date) {
        BlogTagRelationEntity blogTagRelation = new BlogTagRelationEntity();
        blogTagRelation.setId(snowflakeService.getId())
                .setBlogId(blogId)
                .setTagId(tagId)
                .setSort(sort)
                .setDeleteStatus(CommonEnum.DELETE_NO.getValue())
                .setCreateTime(date)
                .setDeleteTime(date);
        return blogTagRelation;
    }
}